#include "drm_encap.h"

#define log(...) do{                 \
            printf("[drm_encap]: ");  \
            printf(__VA_ARGS__);     \
            printf("\n");            \
        } while(0);

static int terminate;
drmModeConnector *conn;	//connetor相关的结构体
drmModeRes *res;		//资源
drmEventContext ev;
int count;

int fd;					//文件描述符
uint32_t conn_id;
uint32_t crtc_id;

int status=0;

#define RED 0XFF0000
#define GREEN 0X00FF00
#define BLUE 0X0000FF


struct drm_device drm_buf[DRM_BUF_NUM];


static int drm_create_fb(struct drm_device *bo)
{
	/* create a dumb-buffer, the pixel format is XRGB888 */
	bo->create.width = bo->width;
	bo->create.height = bo->height;
	bo->create.bpp = 24;

	/* handle, pitch, size will be returned */
	drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &bo->create);

	/* bind the dumb-buffer to an FB object */
	bo->pitch = bo->create.pitch;
	bo->size = bo->create.size;
	bo->handle = bo->create.handle;
	drmModeAddFB(fd, bo->width, bo->height, 24, 24, bo->pitch,
			   bo->handle, &bo->fb_id);

	// drmModeAddFB();
	
	//每行占用字节数，共占用字节数，MAP_DUMB的句柄
	printf("pitch = %d ,size = %d, handle = %d \n",bo->pitch,bo->size,bo->handle);

	/* map the dumb-buffer to userspace */
	bo->map.handle = bo->create.handle;
	drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &bo->map);

	bo->vaddr = mmap(0, bo->create.size, PROT_READ | PROT_WRITE,
			MAP_SHARED, fd, bo->map.offset);

	/* initialize the dumb-buffer with white-color */
	memset(bo->vaddr, 0x00,bo->size);

	return 0;
}

static void drm_destroy_fb(struct drm_device *bo)
{
	struct drm_mode_destroy_dumb destroy = {};

	drmModeRmFB(fd, bo->fb_id);
	
	munmap(bo->vaddr, bo->size);
	
	destroy.handle = bo->handle;

	drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy);
}

int drm_init()
{
    int i;

	//打开drm设备，设备会随设备树的更改而改变,多个设备时，请留一下每个屏幕设备对应的drm设备
	fd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC);
    if(fd < 0){
        printf("wrong\n");
        return 0;
    }

	//获取drm的信息
	res = drmModeGetResources(fd);
	crtc_id = res->crtcs[0];
	conn_id = res->connectors[0];
	//打印CRTCS,以及conneter的id
	printf("crtc = %d , conneter = %d\n",crtc_id,conn_id);

	conn = drmModeGetConnector(fd, conn_id);
	// buf[0].width = conn->modes[0].hdisplay;
	// buf[0].height = conn->modes[0].vdisplay;

	// buf[1].width = conn->modes[0].hdisplay;
	// buf[1].height = conn->modes[0].vdisplay;
    for (i = 0; i < DRM_BUF_NUM; i++) {
        drm_buf[i].width = conn->modes[0].hdisplay;
	    drm_buf[i].height = conn->modes[0].vdisplay;
    }

	//打印屏幕分辨率
	log("width = %d , height = %d\n",drm_buf[0].width, drm_buf[0].height);

	//创建framebuffer层
	// drm_create_fb(&buf[0]);
	// drm_create_fb(&buf[1]);
    for (i = 0; i < DRM_BUF_NUM; i++) {
        drm_create_fb(&drm_buf[i]);
    }

	return 0;
}

int drm_exit()
{
	// drm_destroy_fb(&buf[0]);
	// drm_destroy_fb(&buf[1]);
    for (int i = 0; i < DRM_BUF_NUM; i++) {
        drm_destroy_fb(&drm_buf[i]);
    }

	drmModeFreeConnector(conn);
	drmModeFreeResources(res);
	close(fd);
}

static int drm_flip_num;

static void drm_page_flip_handler(int fd, uint32_t frame,
				    uint32_t sec, uint32_t usec,
				    void *data)
{
	static int i = 0;
	uint32_t crtc_id = *(uint32_t *)data;
	// if(i==0)
	// 	i=1;
	// else if(i==1)
	// 	i=0;
	drmModePageFlip(fd, crtc_id, drm_buf[drm_flip_num].fb_id,
			DRM_MODE_PAGE_FLIP_EVENT, data);
}

int drm_encap_init(void)
{
    ev.version = DRM_EVENT_CONTEXT_VERSION;
	ev.page_flip_handler = drm_page_flip_handler;

    drm_init();
    drmModeSetCrtc(fd, crtc_id, drm_buf[0].fb_id,
			0, 0, &conn_id, 1, &conn->modes[0]);
    drmModePageFlip(fd, crtc_id, drm_buf[0].fb_id,
			DRM_MODE_PAGE_FLIP_EVENT, &crtc_id);
}

int drm_encap_set_fb_num(int num)
{
    if (num >= 0 && num < DRM_BUF_NUM) {
        drm_flip_num = num;
        drmHandleEvent(fd, &ev);
    }
}

int drm_encap_deinit(void)
{
    drm_exit();
}
